home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-04-02 | 14.0 KB | 436 lines | [TEXT/CWIE] |
- /************************************************************************
- ***** File : CDLOGMenuBar.cp *****
- ***** Copyright 1996, Thomas R. Kimpton *****
- ***** All Rights Reserved *****
- ***** *****
- ***** This source code may be freely used in any programming *****
- ***** project so long as credit is duly noted of the author. *****
- ************************************************************************/
-
-
- //************************************************************************
- #pragma mark standard header files
- //************************************************************************
- #include <StdIO.h>
- #include <String.h>
-
- //************************************************************************
- #pragma mark local header files
- //************************************************************************
- #include "CDLOGMenuBar.h"
- #include "Utilities.h"
-
- //************************************************************************
- #pragma mark constant definitions
- //************************************************************************
-
- //************************************************************************
- #pragma mark macro definitions
- //************************************************************************
-
- //************************************************************************
- #pragma mark type definitions
- //************************************************************************
-
- //************************************************************************
- #pragma mark class definitions
- //************************************************************************
-
- //************************************************************************
- #pragma mark static variables
- //************************************************************************
- // These static variables are set just before using the MenuHookProc
- static Rect smMBARRect; // Rect, in window, that comprises the menubar.
- static short smCurMenu; // Index into mMenus for menu currently displayed.
- static auxMenuStruct *smMenus; // Holds the handle and titleRect(within the MBAR) for each menu.
- static Point sUpperLeft; // Used to do a GlobalToLocal() when it's not feasible to make the call...
-
- //************************************************************************
- #pragma mark global variables
- //************************************************************************
-
- //************************************************************************
- #pragma mark forward declarations (prototypes)
- //************************************************************************
-
- //************************************************************************
- #pragma mark external variables
- //************************************************************************
-
- //************************************************************************
- #pragma mark external functions
- //************************************************************************
-
- /************************************************************************
- ***** *****
- ************************************************************************/
-
- /************************************************************************
- ***** Return a new Pane object initialized using data from *****
- ***** a Stream (PPOB object). *****
- ************************************************************************/
- CDLOGMenuBar*
- CDLOGMenuBar::CreatePaneStream( LStream *inStream)
- {
- return (new CDLOGMenuBar(inStream));
- }
-
-
- /************************************************************************
- ***** Default Constructor *****
- ************************************************************************/
- CDLOGMenuBar::CDLOGMenuBar()
- {
-
- short menuBarWidth = 0;
- short numMenus;
- short *menuIDPtr;
- register short i;
- MenuHandle theMenuHndl;
- short menuBoundsPtr;
- Handle theMenuBar;
- unsigned char oldState;
- Rect theFrame;
-
- CalcLocalFrameRect(theFrame);
-
- // Set the mUserCon in Constructor...
- theMenuBar = GetResource(kMBARrsrcType,mUserCon);
- if(!theMenuBar)
- throw;
-
- oldState = HLockState((Handle)theMenuBar);
-
- numMenus = *(short *)*theMenuBar;
- numMenus = (numMenus > kNumMbarMenus) ? kNumMbarMenus : numMenus;
- mNumMenus = numMenus;
-
- menuIDPtr = (short *)*theMenuBar;
- menuIDPtr++; /* Skip over the number of menus. */
- menuBoundsPtr = theFrame.left;
-
- for(i = 0; i < numMenus; i++,menuIDPtr++){
- theMenuHndl = GetMenu(*menuIDPtr);
- mMenus[i].theMenu = theMenuHndl;
- mMenus[i].titleRect.top = theFrame.top;
- mMenus[i].titleRect.bottom = theFrame.bottom;
- mMenus[i].titleRect.left = menuBoundsPtr;
- menuBoundsPtr += StringWidth((ConstStr255Param) (**theMenuHndl).menuData) + 2 * kMenuHMargin;
- mMenus[i].titleRect.right = menuBoundsPtr;
- }
-
- mMBARRect = theFrame;
-
- mCurMenu = -1;
-
- HSetState(theMenuBar,oldState);
- ReleaseResource(theMenuBar);
-
- mMenuHook = NewMenuHookProc(MenuHookProc);
- }
-
-
- /************************************************************************
- ***** Copy Constructor (not tested) *****
- ************************************************************************/
- CDLOGMenuBar::CDLOGMenuBar(const CDLOGMenuBar &inOriginal)
- {
- // Copy members of Original
- mMenuHook = inOriginal.mMenuHook;
- }
-
- /************************************************************************
- ***** Construct Pane from data in a Stream (PPOB object) *****
- ************************************************************************/
- CDLOGMenuBar::CDLOGMenuBar( LStream * inStream ) : LPane(inStream)
- {
- short menuBarWidth = 0;
- short numMenus;
- short *menuIDPtr;
- register short i;
- MenuHandle theMenuHndl;
- short menuBoundsPtr;
- Handle theMenuBar;
- unsigned char oldState;
- Rect theFrame;
- StTextState saveTextState; // Will save and restore text state
-
- // Set the mUserCon in Constructor...
- theMenuBar = GetResource(kMBARrsrcType,mUserCon);
- if(!theMenuBar)
- throw;
-
- mCurMaxNumMbarMenus = kNumMbarMenus;
- mMenus = (auxMenuStruct *)NewPtrClear(mCurMaxNumMbarMenus * sizeof(auxMenuStruct *));
- if(!mMenus || (MemError() != noErr)){
- throw;
- }
- TextFont(systemFont);
- TextSize(0);
-
- mTheSelection = 0;
- mMenuHook = nil;
- mNumMenus = 0;
- mCurMenu = -1;
- CalcLocalFrameRect(theFrame);
-
- oldState = HLockState(theMenuBar);
-
- numMenus = *(short *)*theMenuBar;
- numMenus = (numMenus > kNumMbarMenus) ? kNumMbarMenus : numMenus;
- mNumMenus = numMenus;
-
- menuIDPtr = (short *)*theMenuBar;
- menuIDPtr++; /* Skip over the number of menus. */
- menuBoundsPtr = theFrame.left;
-
- for(i = 0; i < numMenus; i++,menuIDPtr++){
- theMenuHndl = GetMenu(*menuIDPtr);
- mMenus[i].theMenu = theMenuHndl;
- mMenus[i].titleRect.top = theFrame.top;
- mMenus[i].titleRect.bottom = theFrame.bottom;
- mMenus[i].titleRect.left = menuBoundsPtr;
- menuBoundsPtr += StringWidth((ConstStr255Param) (**theMenuHndl).menuData) + 2 * kMenuHMargin;
- mMenus[i].titleRect.right = menuBoundsPtr;
- }
-
- mMBARRect = theFrame;
-
- mCurMenu = -1;
-
- HSetState(theMenuBar,oldState);
- ReleaseResource(theMenuBar);
-
- mMenuHook = NewMenuHookProc(MenuHookProc);
- }
-
-
- /************************************************************************
- ***** Destructor *****
- ************************************************************************/
- CDLOGMenuBar::~CDLOGMenuBar()
- {
- register short i;
-
- for(i=0;i<mNumMenus;i++){
- if(mMenus[i].theMenu)
- ReleaseResource((Handle)mMenus[i].theMenu);
- }
- if(mMenus)
- DisposePtr((Ptr)mMenus);
- if(mMenuHook)
- DisposeRoutineDescriptor(mMenuHook);
- }
-
- /************************************************************************
- ***** Handle MouseDown in DLOGMenuBar. *****
- ************************************************************************/
- void
- CDLOGMenuBar::ClickSelf( const SMouseDownEvent& /* inMouseDown */ )
- {
- Point hitPt;
- MenuHandle theMenu;
- Rect tmpTitleRect;
- Rect titleInvertRect;
- UniversalProcPtr OldMenuHook;
- short i;
- Point loc;
- Rect theFrame;
-
- CalcLocalFrameRect(theFrame);
-
- mTheSelection = 0;
-
- // These static variables are set just before using the MenuHookProc.
- // We have to use static variables, because the MenuHookProc can't access
- // instance variables.
- smMBARRect = mMBARRect; // Rect, in window, that comprises the menubar.
- smMenus = &mMenus[0]; // Holds the handle and titleRect(within the MBAR) for each menu.
- sUpperLeft.v = theFrame.top;
- sUpperLeft.h = theFrame.left;
- LocalToGlobal(&sUpperLeft);
-
- OldMenuHook = LMGetMenuHook();
- LMSetMenuHook((UniversalProcPtr)mMenuHook);
-
- /* A mouseDown in our "menubar" got us into this routine.
- * The routine MenuHookProc() watches where the mouse is and
- * posts a mouseUp event if we get into the menubar and we are
- * not in this menu's title rect. PopUpMenuSelect() looks for
- * this mouseUp and returns. However, the mouse button may really
- * still be down, so we see if we should popup another menu.
- *
- * Because this menubar can be in a movable window, it's possible
- * that the menubar may be down near the bottom of the window, and
- * the menu won't popup(down). So we add code to check to see if
- * the menu will fit on the window. If it won't, we pop the menu
- * UP above the menubar. BUT if the menu is taller than the device
- * AND the menu's in the top half of the screen, we pop it down. phew!
- */
- while(Button()){
- GetMouse(&hitPt);
- for(i = 0; i < mNumMenus; i++){
- tmpTitleRect = mMenus[i].titleRect;
- if(PtInRect(hitPt,&tmpTitleRect)){
- Rect thePortRect;
- short tmpSelection;
-
- mCurMenu = i;
- smCurMenu = mCurMenu; // Index into mMenus for menu currently displayed.
- titleInvertRect = tmpTitleRect;
- InvertRect(&titleInvertRect);
-
- theMenu = mMenus[i].theMenu;
- InsertMenu(theMenu, hierMenu);
- CalcMenuSize(theMenu); /* Is this still necessary? */
- /* Increment them so the menu frame gets drawn correctly */
- loc.h = tmpTitleRect.left + 1;
- loc.v = tmpTitleRect.bottom + 1;
- LocalToGlobal(&loc);
- GetPortRectForThisPoint(loc,&thePortRect);
- if((loc.v + (**theMenu).menuHeight) > thePortRect.bottom){
- short portHeight = thePortRect.bottom - thePortRect.top;
- if(((**theMenu).menuHeight > (portHeight)) &&
- loc.v < (thePortRect.top + portHeight/2)){ // Is the menu taller than the screen, and
- // we're in the top half of the window?
- tmpSelection = 0;
- }
- else{
- loc.h = tmpTitleRect.left + 1;
- loc.v = tmpTitleRect.top - 1;
- tmpSelection = 0x7fff;
- LocalToGlobal(&loc);
- }
- }
- else
- tmpSelection = 0;
- mTheSelection = PopUpMenuSelect(theMenu, loc.v, loc.h, tmpSelection);
- DeleteMenu((**theMenu).menuID);
- InvertRect(&titleInvertRect);
- break;
- } /* PtInRect */
- } /* for */
- } /* while() */
-
- LMSetMenuHook(OldMenuHook);
- if(mTheSelection != 0)
- BroadcastMessage(msg_DLOGMenuBarSelection,(void *)mTheSelection);
- }
-
- /************************************************************************
- ***** Draw the menubar. *****
- ************************************************************************/
- void
- CDLOGMenuBar::DrawSelf()
- {
- register short i;
- MenuHandle theMenu;
- StTextState saveTextState; // Will save and restore text state
-
- TextFont(systemFont);
- TextSize(0);
- RGBColor bgColor = {0xffff,0xffff,0xffff};
- RGBColor fgColor = {0,0,0};
- RGBColor oldbgColor;
- RGBColor oldfgColor;
- GetBackColor(&oldbgColor);
- GetForeColor(&oldfgColor);
-
- RGBForeColor (&fgColor);
- RGBBackColor (&bgColor);
- EraseRect(&mMBARRect);
-
- for(i = 0; i < mNumMenus; i++){
- theMenu = mMenus[i].theMenu;
- ::TETextBox((ConstStr255Param) &(((**theMenu).menuData)[1]),
- (long)(((**theMenu).menuData)[0]),
- &mMenus[i].titleRect,teJustCenter);
- }
- MoveTo((short) mMBARRect.left,(short) mMBARRect.bottom);
- LineTo((short) mMBARRect.right,(short) mMBARRect.bottom);
-
- RGBForeColor (&oldfgColor);
- RGBBackColor (&oldbgColor);
- }
-
- /************************************************************************
- ***** To emulate a menubar we need to post a mouseUp event if *****
- ***** the cursor enters the menubar, but is no longer in the *****
- ***** title rect of the 'current' menu. PopupMenuSelect() watches *****
- ***** for a mouseUp event to tell it to 'collapse' the menu. *****
- ************************************************************************/
- pascal void
- CDLOGMenuBar::MenuHookProc(void)
- {
- Point curPoint;
- short workAround;
-
- GetMouse(&curPoint);
- curPoint.h -= sUpperLeft.h;
- curPoint.v -= sUpperLeft.v;
- workAround = 1; // Had to put this in (for CW) because curPoint was getting munged...???
-
- if(PtInRect(curPoint,&smMBARRect)){
- if(!PtInRect(curPoint,&smMenus[smCurMenu].titleRect)){
- PostEvent(mouseUp,0);
- }
- }
- }
-
- /************************************************************************
- ***** Add a menu to the end of the menubar. *****
- ************************************************************************/
- OSErr
- CDLOGMenuBar::insertMenuDlogMenuBar(MenuHandle theMenu,short *whichMenuIndex)
- {
- Rect frameRect;
- short whichMenu;
- short menuBoundsPtr;
-
- mNumMenus++;
- if(mNumMenus >= (mCurMaxNumMbarMenus - 1)){
- auxMenuStruct *tmpMenus;
- mCurMaxNumMbarMenus += kMbarMenusIncr;
- // Doing it this way is less likely to fail than doing a SetPtrSize().
- tmpMenus = (auxMenuStruct *)NewPtrClear(mCurMaxNumMbarMenus * sizeof(auxMenuStruct *));
- if(!tmpMenus || (MemError() != noErr)){
- mCurMaxNumMbarMenus -= kMbarMenusIncr;
- --mNumMenus;
- return(MemError());
- }
- memcpy(tmpMenus,mMenus,(mNumMenus - 1) * sizeof(auxMenuStruct *));
- DisposePtr((Ptr)mMenus);
- mMenus = tmpMenus;
- }
- CalcLocalFrameRect(frameRect);
-
-
- menuBoundsPtr = frameRect.right;
-
- whichMenu = mNumMenus - 1;
- mMenus[whichMenu].theMenu = theMenu;
- mMenus[whichMenu].titleRect.top = frameRect.top;
- mMenus[whichMenu].titleRect.bottom = frameRect.bottom;
- mMenus[whichMenu].titleRect.left = menuBoundsPtr;
- menuBoundsPtr += StringWidth((ConstStr255Param) (**theMenu).menuData) + 2 * kMenuHMargin;
- mMenus[whichMenu].titleRect.right = menuBoundsPtr;
-
- *whichMenuIndex = whichMenu;
-
- return(noErr);
- }
-
- /************************************************************************
- ***** Return the menuHandle that corresponds to whichMenuIndex. *****
- ************************************************************************/
- MenuHandle
- CDLOGMenuBar::getDlogMenuBarMenu(short whichMenuIndex)
- {
-
- if(whichMenuIndex > (mNumMenus - 1))
- return(nil);
- else
- return(mMenus[whichMenuIndex].theMenu);
- }
-
-